﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using SharedGenomics.Annotations;
using SharedGenomics.Workbench.Annotations;

namespace SharedGenomics.Workbench.Tests.Annotations
{
    [TestClass]
    public class AnnotationRequestContextTests
    {
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ConstructorShouldThrowIfKeyNull()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(null, "rs1");
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ConstructorShouldThrowIfTargetNull()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(AnnotationKey.Gene, null);
        }

        [TestMethod]
        public void ShouldAddAnnotation()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(AnnotationKey.GoogleSearch, "rs1");
            var searchAnnotation = new GoogleSearchAnnotation("rs1");

            context.AddAnnotation(searchAnnotation, new AnnotationValue(AnnotationKey.SnpName, "rs1"));
            Assert.IsTrue(context.ContainsResultFor(AnnotationKey.GoogleSearch));
            Assert.IsInstanceOfType(context.Results.First(), typeof(SucceededAnnotationRequestResult));
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ShouldThrowIfAnnotationNull()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(AnnotationKey.GoogleSearch, "rs1");
            context.AddAnnotation(null, new AnnotationValue(AnnotationKey.SnpName, "rs1"));
        }

        [TestMethod]
        public void ShouldFailAnnotation()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(AnnotationKey.GoogleSearch, "rs1");

            context.FailRequest(AnnotationKey.GoogleSearch);
            Assert.IsTrue(context.ContainsResultFor(AnnotationKey.GoogleSearch));
            Assert.IsInstanceOfType(context.Results.First(), typeof(FailedAnnotationRequestResult));
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ShouldThrowIfKeyNull()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(AnnotationKey.GoogleSearch, "rs1");
            context.FailRequest(null);
        }

        [TestMethod]
        public void ShouldNotContainResultForNullKey()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(AnnotationKey.GoogleSearch, "rs1");
            Assert.IsFalse(context.ContainsResultFor(null));
        }

        [TestMethod]
        public void ShouldSucceedPreviouslyFailedAnnotation()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(AnnotationKey.GoogleSearch, "rs1");

            context.FailRequest(AnnotationKey.GoogleSearch);
            context.AddAnnotation(new GoogleSearchAnnotation("rs1"), new AnnotationValue(AnnotationKey.SnpName, "rs1"));

            Assert.AreEqual(1, context.Results.Count());
            Assert.IsInstanceOfType(context.Results.First(), typeof(SucceededAnnotationRequestResult));
        }

        [TestMethod]
        public void ShouldAddValue()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(AnnotationKey.NcbiSummary, "rs1");

            context.AddValue(new AnnotationValue(AnnotationKey.EntrezGeneId, 1234), new AnnotationValue(AnnotationKey.SnpName, "rs1"));
            var output = context.OutputArtifacts.First();
            Assert.AreEqual(AnnotationKey.EntrezGeneId, output.Key);
            Assert.AreEqual(1234, output.Value);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ShouldThrowIfValueNull()
        {
            AnnotationRequestContext context = new AnnotationRequestContext(AnnotationKey.NcbiSummary, "rs1");
            context.AddValue(null, new AnnotationValue(AnnotationKey.SnpName, "rs1"));
        }
    }
}
